﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace SnippetBox.Core.Common.Paging {
    public static class PagingExtensions {
        #region HtmlHelper extensions

        public static IHtmlString Pager<T>(this HtmlHelper html, IPagedList<T> pagedList) {
            return Pager(html, pagedList.PageSize, pagedList.PageNumber, pagedList.TotalItemCount, null, null);
        }

        public static IHtmlString Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount) {
            return Pager(htmlHelper, pageSize, currentPage, totalItemCount, null, null);
        }

        public static IHtmlString Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount,
                                   string actionName) {
            return Pager(htmlHelper, pageSize, currentPage, totalItemCount, actionName, null);
        }

        public static IHtmlString Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount,
                                   object values) {
            return Pager(htmlHelper, pageSize, currentPage, totalItemCount, null, new RouteValueDictionary(values));
        }

        public static IHtmlString Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount,
                                   string actionName, object values) {
            return Pager(htmlHelper, pageSize, currentPage, totalItemCount, actionName, new RouteValueDictionary(values));
        }

        public static IHtmlString Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount,
                                   RouteValueDictionary valuesDictionary) {
            return Pager(htmlHelper, pageSize, currentPage, totalItemCount, null, valuesDictionary);
        }

        public static IHtmlString Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount,
                                   string actionName, RouteValueDictionary valuesDictionary) {
            if (valuesDictionary == null) {
                valuesDictionary = new RouteValueDictionary();
            }
            if (actionName != null) {
                if (valuesDictionary.ContainsKey("action")) {
                    throw new ArgumentException("The valuesDictionary already contains an action.", "actionName");
                }
                valuesDictionary.Add("action", actionName);
            }
            var pager = new Pager(htmlHelper.ViewContext, pageSize, currentPage, totalItemCount, valuesDictionary);
            return new HtmlString(pager.RenderHtml());
        }

        public static IHtmlString Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount,
                                   string actionName, string controller, RouteValueDictionary valuesDictionary) {
            if (valuesDictionary == null) {
                valuesDictionary = new RouteValueDictionary();
            }

            if (actionName != null) {
                if (valuesDictionary.ContainsKey("action")) {
                    throw new ArgumentException("The valuesDictionary already contains an action.", "actionName");
                }
                valuesDictionary.Add("action", actionName);
            }

            if (controller != null) {
                if (valuesDictionary.ContainsKey("controller")) {
                    throw new ArgumentException("The valuesDictionary already contains a controller.", "controllerName");
                }
                valuesDictionary.Add("controller", controller);
            }
            var pager = new Pager(htmlHelper.ViewContext, pageSize, currentPage, totalItemCount, valuesDictionary);
            return new HtmlString(pager.RenderHtml());
        }

        #endregion

        #region IQueryable<T> extensions

        public static IPagedList<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize) {
            return new PagedList<T>(source, pageIndex, pageSize);
        }

        public static IPagedList<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize,
                                                   int totalCount) {
            return new PagedList<T>(source, pageIndex, pageSize, totalCount);
        }

        public static IPagedList<T> ToPagedList<T>(this IQueryable<T> source, int? page, int pageSize) {
            var pageIndex = page.HasValue ? page.Value - 1 : 0;
            return new PagedList<T>(source, pageIndex, pageSize);
        }

        public static IPagedList<T> ToPagedList<T>(this IQueryable<T> source, int? page, int pageSize,
                                                   int totalCount) {
            var pageIndex = page.HasValue ? page.Value - 1 : 0;
            return new PagedList<T>(source, pageIndex, pageSize, totalCount);
        }

        #endregion

        #region IEnumerable<T> extensions

        public static IPagedList<T> ToPagedList<T>(this IEnumerable<T> source, int pageIndex, int pageSize) {
            return new PagedList<T>(source, pageIndex, pageSize);
        }

        public static IPagedList<T> ToPagedList<T>(this IEnumerable<T> source, int pageIndex, int pageSize,
                                                   int totalCount) {
            return new PagedList<T>(source, pageIndex, pageSize, totalCount);
        }

        public static IPagedList<T> ToPagedList<T>(this IEnumerable<T> source, int? page, int pageSize) {
            var pageIndex = page.HasValue ? page.Value - 1 : 0;
            return new PagedList<T>(source, pageIndex, pageSize);
        }

        public static IPagedList<T> ToPagedList<T>(this IEnumerable<T> source, int? page, int pageSize,
                                                   int totalCount) {
            var pageIndex = page.HasValue ? page.Value - 1 : 0;
            return new PagedList<T>(source, pageIndex, pageSize, totalCount);
        }

        #endregion
    }
}